package httpserver

import (
	"fmt"
	"gitee.com/scottq/go-framework/src/utils"
	"golang.org/x/time/rate"
	"net/http"
	"runtime/debug"
)

//DefaultResponseMiddleware response
var DefaultResponseMiddleware Middleware = func(ctx *Ctx, next func(*Ctx)) {
	ctx.SetResponseHandler(NewHttpResponse(ctx.Writer()))
	next(ctx)
}

//GlobalMiddlewareQPSLimiter qps限流
var GlobalMiddlewareQPSLimiter = func(r rate.Limit, b int) Middleware {
	limiter := rate.NewLimiter(r, b)
	return func(ctx *Ctx, next func(ctx *Ctx)) {
		if !limiter.Allow() {
			ctx.writer.WriteHeader(http.StatusNoContent)
			return
		}

		next(ctx)
	}
}

//GlobalMiddlewarePanic panic处理
var GlobalMiddlewarePanic Middleware = func(ctx *Ctx, next func(*Ctx)) {
	defer func() {
		if err := recover(); err != nil {
			debug.PrintStack()
			fmt.Printf("panic:%s\n",err)
			ctx.WriteHeader(http.StatusInternalServerError)
			ctx.SetMsg(fmt.Sprintf("panic:%s",err))
			ctx.Response()
			return
		}
	}()
	next(ctx)
}

//GlobalMiddlewareAddRequestId 添加requestId
var GlobalMiddlewareAddRequestId = func(requestIdField string) Middleware {
	return func(ctx *Ctx, next func(*Ctx)) {

		//添加requestId
		//c := context.WithValue(ctx.request.Context(), requestIdField, utils.NewRequestId())
		//ctx.request = ctx.request.WithContext(c)

		//改为直接ctx接收requestId
		ctx.SetRequestId(utils.NewRequestId())

		next(ctx)
	}
}

//GlobalMiddlewareOptionRequest OPTION请求过滤
var GlobalMiddlewareOptionRequest Middleware = func(ctx *Ctx, next func(*Ctx)) {
	if ctx.request.Method == "OPTIONS" {
		ctx.writer.WriteHeader(http.StatusNoContent)
		return
	}
	next(ctx)
}

//GlobalMiddlewareCorsMiddleware 跨域资源请求
var GlobalMiddlewareCorsMiddleware = func(domainWhites []string) Middleware {
	return func(ctx *Ctx, next func(*Ctx)) {
		allow := false

		//跨域设置
		if origin := ctx.request.Header.Get("Origin"); origin != "" {
			if domainWhites == nil {
				allow = true
			} else {
				for _, white := range domainWhites {
					if white == origin {
						allow = true
						break
					}
				}
			}
			if allow {
				ctx.writer.Header().Set("Access-Control-Allow-Origin", origin)
			}
		}
		ctx.writer.Header().Set("Access-Control-Allow-Credentials", "true")
		ctx.writer.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
		ctx.writer.Header().Set("Access-Control-Allow-Headers", "Content-type,Authorization,x-requested-with,Request-Service")

		next(ctx)
	}
}

const limiterR = 100
const limiterInit = 100
const requestIdFiled = "RequestId"

var BaseMiddlewareArr = []Middleware{
	GlobalMiddlewarePanic,
	GlobalMiddlewareAddRequestId(requestIdFiled),
	GlobalMiddlewareCorsMiddleware(nil),
	GlobalMiddlewareOptionRequest,
}

var HealthMiddlewareArr = []Middleware{
	GlobalMiddlewarePanic,
	GlobalMiddlewareAddRequestId(requestIdFiled),
	GlobalMiddlewareCorsMiddleware(nil),
	GlobalMiddlewareOptionRequest,
	GlobalMiddlewareQPSLimiter(limiterR, limiterInit),
}

//HealthF 健康检查func
func HealthF(ctx *Ctx) {
	ctx.Write([]byte("ok"))
}
